Skip to content

Add libraries field to the clusters resource - #6365

Open
Sankalp-Mittal wants to merge 14 commits into
mainfrom
sankalp-mittal/all-purpose-cluster-libraries
Open

Add libraries field to the clusters resource#6365
Sankalp-Mittal wants to merge 14 commits into
mainfrom
sankalp-mittal/all-purpose-cluster-libraries

Conversation

@Sankalp-Mittal

@Sankalp-Mittal Sankalp-Mittal commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a libraries list to the clusters resource in DABs, so libraries (whl, jar, pypi, maven, cran, egg, requirements) can be installed on an all-purpose cluster directly from a bundle. Local wheels and jars are built and uploaded automatically. Fixes #1860.

resources:
  clusters:
    mycluster:
      # ...
      libraries:
        - pypi:
            package: requests
        - whl: ./dist/*.whl

Design choices

  • Modeled as a child resource of the cluster, installed via the Libraries API (install/uninstall) rather than as part of cluster create/edit. Libraries have their own lifecycle: they install on a running cluster without a restart, and the cluster_id reference guarantees the cluster is RUNNING before install begins.

  • Direct engine only. Cluster libraries are rejected under the Terraform engine and only supported for Direct

  • Reuses the existing wheel build/upload pipeline so whl: ./dist/*.whl and other local artifacts are built and rewritten to their uploaded workspace paths, consistent with how job/task libraries already work.

Testing

Acceptance tests cover deploy/install, wheel rewrite, uninstall-on-removal, the Terraform-engine rejection, and no-drift on a real workspace. The library-status API round-trips cleanly, so no normalization step is needed.

@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 6b15637

Run: 32866130743

Env 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
💚​ aws linux 2 3 287 1479 29:13
💚​ aws windows 2 3 289 1477 41:12
💚​ azure linux 2 3 286 1479 7:21
💚​ azure windows 2 3 288 1477 8:58
💚​ gcp linux 2 3 287 1479 10:39
💚​ gcp windows 2 3 289 1477 11:29
Test Name aws linux aws windows azure linux azure windows gcp linux gcp windows
💚​ TestAccept 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
💚​ TestAccept/bundle/invariant/no_drift 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_indexes/recreate/embedding_dimension 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
Top 46 slowest tests (at least 2 minutes):
duration env testname
30:01 aws windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
21:04 aws windows TestAccept/bundle/resources/clusters/libraries-drift/DATABRICKS_BUNDLE_ENGINE=direct
19:32 aws linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
8:27 aws linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
8:20 aws linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
7:55 aws linux TestAccept/bundle/resources/clusters/libraries-drift/DATABRICKS_BUNDLE_ENGINE=direct
7:54 aws windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
7:49 aws windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
7:45 aws windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
7:34 aws linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
7:13 aws windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
7:07 aws linux TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
6:22 gcp windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
5:40 gcp linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
5:05 gcp linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
4:19 aws windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
4:18 gcp windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
4:03 gcp linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
3:57 gcp windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
3:41 aws linux TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
3:40 gcp windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
3:36 gcp windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
3:15 aws windows TestAccept
3:11 gcp linux TestAccept/bundle/resources/clusters/libraries-drift/DATABRICKS_BUNDLE_ENGINE=direct
3:11 azure windows TestAccept
3:08 gcp linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
3:07 gcp windows TestAccept
3:07 gcp windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
3:05 gcp linux TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
3:02 gcp linux TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
2:56 azure windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:55 azure windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
2:53 azure linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:49 azure linux TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
2:45 azure windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:44 azure windows TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
2:38 gcp windows TestAccept/bundle/resources/clusters/libraries-drift/DATABRICKS_BUNDLE_ENGINE=direct
2:34 azure linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
2:26 azure linux TestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:22 azure linux TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
2:22 azure windows TestAccept/bundle/invariant/no_drift/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=1
2:22 azure linux TestAccept/bundle/resources/clusters/libraries-drift/DATABRICKS_BUNDLE_ENGINE=direct
2:17 azure linux TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:16 azure windows TestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_libraries.yml.tmpl/READPLAN=
2:16 azure windows TestAccept/bundle/resources/clusters/libraries-drift/DATABRICKS_BUNDLE_ENGINE=direct
2:01 gcp linux TestFilerWorkspaceFilesExtensionsRead

@Sankalp-Mittal
Sankalp-Mittal force-pushed the sankalp-mittal/all-purpose-cluster-libraries branch from e378a6a to e4e688e Compare August 25, 2026 09:36
Sankalp-Mittal and others added 13 commits August 25, 2026 13:57
Wire the direct engine to treat resources.clusters.*.libraries as a
child-resource node, the same way permissions and grants are handled:
node/type resolution, reference splitting, and plan node discovery.

Co-authored-by: Isaac <no-reply@databricks.com>
Implement ResourceLibraries: installs/uninstalls cluster libraries via
the Libraries API, reconciling removed libraries on update and polling
for install completion on a running cluster. Registered in all.go.

Note: TestAll/clusters.libraries fails until the testserver models the
libraries install/uninstall/cluster-status endpoints (next step).

Co-authored-by: Isaac <no-reply@databricks.com>
Add stateful fakes for the Libraries API (install, uninstall,
cluster-status) so clusters.libraries runs against the in-process
server. Add the TestAll fixture and classify libraries as a no-op
delete alongside permissions/grants; this greens TestAll/clusters.libraries.

Co-authored-by: Isaac <no-reply@databricks.com>
Add clusterLibrariesPattern (resources.clusters.*.libraries) to glob
expansion, local-library collection/upload, duplicate-name checking,
and patched-wheel swapping, mirroring the job task library wiring. Local
whl/jar globs now build, upload to artifact_path/.internal, and rewrite
to absolute workspace paths; pypi/maven entries pass through unchanged.

Co-authored-by: Isaac <no-reply@databricks.com>
Add ValidateClusterLibraries and register it in PreDeployChecks so a
libraries block on a cluster errors under the terraform engine instead
of being silently dropped. Cluster libraries are direct-only. Mirrors
the existing lifecycle.started guard.

Co-authored-by: Isaac <no-reply@databricks.com>
Adding the clusters libraries field makes DABs libraries map to the
terraform databricks_cluster.library field; regenerate the mapping so
reference translation and the tf-only field audit stay correct.

Co-authored-by: Isaac <no-reply@databricks.com>
- clusters/libraries: direct-engine deploy installs pypi + local wheel
  (rewritten to its uploaded path), and removing the wheel and
  redeploying uninstalls it.
- clusters/libraries-terraform-error: bundle plan/deploy reject cluster
  libraries under the terraform engine.

Co-authored-by: Isaac <no-reply@databricks.com>
Enumerate the remaining LibraryInstallStatus cases in the install-wait
poll and set EmbeddedSlice explicitly in DoRead's state literal.

Co-authored-by: Isaac <no-reply@databricks.com>
clusters/libraries-drift (Cloud = true, direct engine): deploy a cluster
with a pypi library, then assert the immediate re-plan is a no-op
(0 to change). Verified on a real AWS workspace: the Libraries status API
round-trips the library without drift, so no normalization is needed.

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
Pipelines have a native libraries field that is a plain field, not a
child resource. The sub-resource wiring matched resources.*.*.libraries
for every resource type, so the direct engine tried to plan
pipelines.libraries as a resource and failed with 'unsupported resource
type: pipelines.libraries'. Scope both GetNodeAndType and the plan
pattern to clusters.

Co-authored-by: Isaac <no-reply@databricks.com>
Consistency follow-up to the GetNodeAndType/plan-pattern scoping:
ResourcesTypes registered a .libraries key for every resource type with
a Libraries field, spuriously adding pipelines.libraries and
cluster_policies.libraries. Those keys are unreachable now that
GetNodeAndType is scoped, but scope this branch too so the map stays
consistent and the entries don't mislead future callers.

Co-authored-by: Isaac <no-reply@databricks.com>
Two CI failures in the local acceptance suite:

1. bundle/resources/clusters/libraries deployed a prebuilt wheel from
   ./dist/*.whl, but dist/ is gitignored so the fixture was never
   committed. CI's clean checkout hit 'no files match pattern:
   ./dist/*.whl'. Force-add the dummy wheel as a committed test input.

2. TestInvariantConfigsCoverage requires every config.ResourcesTypes key
   to be covered. clusters.libraries had no coverage: the scanner only
   understood .permissions/.grants sub-resources. Teach it .libraries
   too, add a pypi-only cluster_libraries invariant config, and wire it
   into INPUT_CONFIG. Cluster libraries are direct-only, so exclude the
   config from the terraform-seeded migrate subtest like the other
   direct-only resources.

Co-authored-by: Isaac <no-reply@databricks.com>
@Sankalp-Mittal Sankalp-Mittal changed the title add libraries field for Clusters Add libraries field to the clusters resource Aug 26, 2026
@Sankalp-Mittal
Sankalp-Mittal marked this pull request as ready for review August 26, 2026 08:19
@github-actions

Copy link
Copy Markdown
Contributor

Approval status: pending

/acceptance/bundle/ - needs approval

24 files changed
Suggested: @denik
Also eligible: @pietern, @janniklasrose, @andrewnester, @shreyas-goenka, @anton-107, @lennartkats-db

/bundle/ - needs approval

18 files changed
Suggested: @denik
Also eligible: @pietern, @janniklasrose, @andrewnester, @shreyas-goenka, @anton-107, @lennartkats-db

General files (require maintainer)

5 files changed
Based on git history:

  • @denik -- recent work in libs/testserver/, bundle/direct/, bundle/direct/dresources/

Any maintainer (@andrewnester, @anton-107, @denik, @pietern, @shreyas-goenka, @simonfaltum, @renaudhartert-db, @janniklasrose, @lennartkats-db, @rugpanov, @rclarey) can approve all areas.
See OWNERS for ownership rules.

@Sankalp-Mittal

Copy link
Copy Markdown
Collaborator Author

Check if a library is changes and all others are unchanged, does only reinstalling the change library work or can others have a dependency on it and everything needs to be reinstalled

return nil, nil
}

// DoDelete is a no-op: removing individual libraries is handled by DoUpdate's uninstall diff, and

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the entire libraries node is removed? That should be a delete on libraries

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: configure all-purpose cluster libraries through DAB

2 participants